package org.jef.auth.support.wechat;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.jef.auth.support.base.OAuth2ResourceOwnerBaseAuthenticationProvider;
import org.jef.core.constant.SecurityConstants;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.oauth2.core.AuthorizationGrantType;
import org.springframework.security.oauth2.core.OAuth2AuthenticationException;
import org.springframework.security.oauth2.core.OAuth2ErrorCodes;
import org.springframework.security.oauth2.core.OAuth2Token;
import org.springframework.security.oauth2.server.authorization.OAuth2AuthorizationService;
import org.springframework.security.oauth2.server.authorization.client.RegisteredClient;
import org.springframework.security.oauth2.server.authorization.token.OAuth2TokenGenerator;

import java.util.Map;
import java.util.Set;

/**
 * @version 1.0
 * @program: OAuth2ResourceOwnerWechatAuthenticationProvider
 * @description: 微信授权
 * @author: ChengZhi 0336
 * @create: 2024-08-05 17:46
 **/
public class OAuth2ResourceOwnerWechatAuthenticationProvider
		extends OAuth2ResourceOwnerBaseAuthenticationProvider<OAuth2ResourceOwnerWechatAuthenticationToken> {

	private static final Logger LOGGER = LogManager.getLogger(OAuth2ResourceOwnerWechatAuthenticationProvider.class);

	/**
	 * Constructs an {@code OAuth2AuthorizationCodeAuthenticationProvider} using the
	 * provided parameters.
	 * @param authenticationManager
	 * @param authorizationService the authorization service
	 * @param tokenGenerator the token generator
	 * @since 0.2.3
	 */
	public OAuth2ResourceOwnerWechatAuthenticationProvider(AuthenticationManager authenticationManager,
                                                           OAuth2AuthorizationService authorizationService,
                                                           OAuth2TokenGenerator<? extends OAuth2Token> tokenGenerator) {
		super(authenticationManager, authorizationService, tokenGenerator);
	}

	@Override
	public UsernamePasswordAuthenticationToken buildToken(Map<String, Object> reqParameters) {
		String jsCode = (String) reqParameters.get(SecurityConstants.WECHAT_PARAMETER_JSCODE);
		String encryptedData = (String) reqParameters.get(SecurityConstants.WECHAT_PARAMETER_ENCRYPTEDDATA);
		String iv = (String) reqParameters.get(SecurityConstants.WECHAT_PARAMETER_IV);

		String code = jsCode + "_" + encryptedData + "_" + iv;

		return new UsernamePasswordAuthenticationToken(code, null);
	}

	@Override
	public boolean supports(Class<?> authentication) {
		boolean supports = OAuth2ResourceOwnerWechatAuthenticationToken.class.isAssignableFrom(authentication);
		LOGGER.debug("supports authentication=" + authentication + " returning " + supports);
		return supports;
	}

	@Override
	public void checkClient(RegisteredClient registeredClient) {
		assert registeredClient != null;
		Set<AuthorizationGrantType> authorizationGrantTypes = registeredClient.getAuthorizationGrantTypes();
		if (!authorizationGrantTypes.contains(new AuthorizationGrantType(SecurityConstants.WECHAT))) {
			throw new OAuth2AuthenticationException(OAuth2ErrorCodes.UNAUTHORIZED_CLIENT);
		}
	}

}
